﻿#include "FITKCCXAdaptorCase.h"
#include "FITKCCXAdaptorModel.h"
#include "FITKCCXAdaptorPart.h"
#include "FITKCCXAdaptorSet.h"
#include "FITKCCXAdaptorConstraint.h"
#include "FITKCCXAdaptorAmplitude.h"
#include "FITKCCXAdaptorMaterial.h"
#include "FITKCCXAdaptorBoundary.h"
#include "FITKCCXAdaptorInteraction.h"
#include "FITKCCXAdaptorStep.h"
#include "FITKCCXAdaptorInteractionProperty.h"
#include "FITKCalculixINPWriter.h"
#include "FITKCalculixINPReader.h"
#include "InpKeyLineSpliter.h"
#include "FITK_Kernel/FITKAdaptor/FITKIOAdaptorFactory.h"
#include "FITK_Interface/FITKInterfaceModel/FITKModelSet.h"
#include "FITK_Interface/FITKInterfaceModel/FITKComponentManager.h"
#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMaterial.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAssembly.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractStep.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepInit.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepFrequency.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepGeneralStatic.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepDynamicExplicit.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractAmplitude.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudePeriodic.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudeTabular.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudeManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractBoundaryCondition.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionDisplacement.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionSymmetry.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionPropertyContact.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionPropertyManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionSurfToSurfExplicit.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionGeneralContactExplicit.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConstraintCoupling.h" 
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConstraintTie.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConstraintRigidBody.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConstraintManager.h"

namespace IO
{
    QString FITKCCXAdaptorCase::getAdaptorClass()
    {
        return "IO::FITKCCXAdaptorCase";
    }

    bool FITKCCXAdaptorCase::adaptR()
    {
        _caseData = AbaqusData::FITKDataCase::SafeDownCastFITKDataCase(_dataObj);
        if (_caseData == nullptr || _reader == nullptr) return false;
        
        AbaqusData::FITKAbaqusPartManager* partMgr =  _caseData->getPartManager();
        if (partMgr == nullptr) return false;
        QString name = partMgr->checkName("Part-1");
        const int n = partMgr->getDataCount();
        AbaqusData::FITKAbaqusPart *p = new AbaqusData::FITKAbaqusPart;;
        p->setDataObjectName(name);
        partMgr->appendDataObj(p);
      
        bool readOK = true;

        QString currentLine;
        while (!_reader->atEnd())
        {
            
            currentLine = _reader->readLine();
            if (!currentLine.startsWith("*")) continue;

            InpKeyLineSpliter keySpliter(currentLine, _reader);
            const QString sheader = keySpliter.getHeader().toLower();

            if (sheader == "node" || sheader == "element")
            {
                //读取
                auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorPart>("CCXINP", p);
                if (adaptor == nullptr) return false;
                adaptor->setFileReader(_reader);
                adaptor->setDataObject(p);
                readOK &= adaptor->adaptR();
                delete adaptor;
                _reader->backLine();
            }
            else if (sheader == "nset" || sheader == "elset")
            {
                //创建集合
                auto  aset = new Interface::FITKModelSet;
                aset->setModel(p);
                auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorSet>("CCXINP", aset);
                if (adaptor == nullptr)
                {
                    delete aset;
                    return false;
                }
                //读取
                adaptor->setFileReader(_reader);
                adaptor->setDataObject(aset);
                bool ok = adaptor->adaptR();
                if(!ok)
                {
                    delete adaptor;
                    return false;
                }
                delete adaptor;
                //保存数据
                auto cMgr = p->getComponentManager();
                if (cMgr)
                    cMgr->appendDataObj(aset);
                readOK &= ok;
                _reader->backLine();
            }
        }
        return readOK;
    }

    bool FITKCCXAdaptorCase::adaptW()
    {
        _caseData = AbaqusData::FITKDataCase::SafeDownCastFITKDataCase(_dataObj);
        _modelInfoManager = new FITKCCXModelInforManager();
        if (_writer == nullptr || _caseData == nullptr || _modelInfoManager == nullptr) return false;

        // 写出函数主体
        QTextStream* stream = _writer->getStream();
        if (stream == nullptr) return false;
        bool isW = true;

        // 写出头
        writeHeading();
        
        // libaojun@20240602
        Interface::FITKAbaAssembly* assembly = _caseData->getAssembly();
        if (assembly && assembly->getDataCount() > 0)
        {
            isW &= this->writeModel(assembly);
        }

        // 写出Amplitude
        int amplitudeNum = _caseData->getAmplitudeManager()->getDataCount();
        if (amplitudeNum > 0)
        {
            for (int i = 0; i < amplitudeNum; ++i)
            {
                auto absAmplitude = _caseData->getAmplitudeManager()->getDataByIndex(i);
                auto amplitude = dynamic_cast<Interface::FITKAbaAbstractAmplitude*>(absAmplitude);
                if (!amplitude) continue;
                isW &= this->writeAmplitude(amplitude);
            }
        }

        // 写出约束
        isW &= writeCCXConstraint();

        //写出Material
        int materialNum = _caseData->getMaterialManager()->getDataCount();
        if (materialNum > 0)
        {
            *stream << "**" << endl;
            *stream << "** MATERIALS" << endl;
            *stream << "**" << endl;
            for (int i = 0; i < materialNum; ++i)
            {
                auto absMaterial = _caseData->getMaterialManager()->getDataByIndex(i);
                auto material = dynamic_cast<Interface::FITKAbaMaterial*>(absMaterial);
                if (!material) continue;
                isW &= this->writeCCXMaterial(material);
            }
        }

        // 写出相互作用属性
        isW &= writeCCXInteractionProperty();

        // 写出初始分析步中的边界条件
        isW &= writeCCXInitialBoundary();

        // 写出分析步
        int stepNum = _caseData->getStepManager()->getDataCount();
        if (stepNum > 1)
        {
            for (int i = 1; i < stepNum; ++i)
            {
                auto absStep = _caseData->getStepManager()->getDataByIndex(i);

                *stream << "** ----------------------------------------------------------------" << endl;
                *stream << "**" << endl;
                *stream << QString("** STEP: %1").arg(absStep->getDataObjectName()) << endl;
                *stream << "**" << endl;
                auto step = dynamic_cast<Interface::FITKAbaAbstractStep*>(absStep);
                if (!step) continue;
                isW &= writeCCXStep(step);
                *stream << "*End Step" << endl;
                
            }
        }

        if (isBothCouplingDynamic())
        {
            // 写出不支持动态分析步中包含coupling约束类型
            _writer->consoleMessage(2, "Calculix does not support coupling is included in the dynamic analysis step");
        }

        // 删除映射关系指针
        if (_modelInfoManager)
        {
            _modelInfoManager = nullptr;
            delete _modelInfoManager;        
        }
        return true;
    }

    bool FITKCCXAdaptorCase::writeHeading()
    {
        // 写出节点函数主体
        QTextStream* stream = _writer->getStream();

        //写出固定头信息 Model Generated 暂时没读 暂时默认
        *stream << "*Heading" << endl;
        *stream << "** Model name: " << _caseData->getDataObjectName() << endl;
        *stream << "** Generated by: Calculix" << endl;
        return true;
    }

    bool FITKCCXAdaptorCase::writeModel(Interface::FITKAbaAssembly* assembly)
    {
        // 通过工厂创建
        auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorModel>("CCXINP", assembly);
        if (adaptor == nullptr) return false;
        adaptor->setFileWriter(_writer);
        adaptor->setDataObject(assembly);
        adaptor->setCaseData(_caseData);
        adaptor->setModelInfoManager(_modelInfoManager);
        bool ok = adaptor->adaptW();
        delete adaptor;

        //错误输出的含义是什么？  libaojun，通知哪个文件哪一行出现了问题
        if (!ok) 
            _writer->consoleMessage(3, QString("Write Model Error,File:%1 Line:%2").arg(__FILE__).arg(__LINE__));
        return ok;
    }

    bool FITKCCXAdaptorCase::writeCCXConstraint()
    {
        auto constraintManager = _caseData->getConstraintManager();
        if (!constraintManager)return false;
        int count = constraintManager->getDataCount();
        bool ok = true;
        QTextStream* stream = _writer->getStream();
        for (int i = 0; i < count; ++i)
        {
            auto data = constraintManager->getDataByIndex(i);
            Interface::FITKAbaAbstractConstraint* constraint = dynamic_cast<Interface::FITKAbaAbstractConstraint*>(data);
            if (!constraint)continue;

            //通过工厂创建
            auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorConstraint>("CCXINP", constraint);
            if (adaptor == nullptr) return false;
            *stream << QString("** Constraint: Constraint-%1").arg(i + 1) << endl;
            adaptor->setFileWriter(_writer);
            adaptor->setCaseData(_caseData);
            adaptor->setDataObject(constraint);
            adaptor->setModelInfoManager(_modelInfoManager);
            ok = adaptor->adaptW();
            delete adaptor;
            if (!ok)
                _writer->consoleMessage(3, QString("write Calculix Constraint Error,File:%1 Line:%2").arg(__FILE__).arg(__LINE__));
            if (!ok) return false;
        }
        return true;
    }

    bool FITKCCXAdaptorCase::writeAmplitude(Interface::FITKAbaAbstractAmplitude* amplitude)
    {
        // 通过工厂创建
        auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorAmplitude>("CCXINP", amplitude);
        if (adaptor == nullptr) return false;

        //设置写出器
        adaptor->setFileWriter(_writer);
        adaptor->setDataObject(amplitude);
        bool ok = adaptor->adaptW();
        delete adaptor;
        if (!ok)
            _writer->consoleMessage(3, QString("Write Amplitude Error,File:%1 Line:%2").arg(__FILE__).arg(__LINE__));
        return ok;
    }

    bool FITKCCXAdaptorCase::writeCCXMaterial(Interface::FITKAbaMaterial* material)
    {
       

        // 通过工厂创建
        auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorMaterial>("CCXINP", material);
        if (adaptor == nullptr) return false;

        //设置写出器
        adaptor->setFileWriter(_writer);
        adaptor->setDataObject(material);
        bool ok = adaptor->adaptW();
        delete adaptor;
        if (!ok)
            _writer->consoleMessage(3, QString("Write Material Error,File:%1 Line:%2").arg(__FILE__).arg(__LINE__));
        return ok;
    }

    bool FITKCCXAdaptorCase::writeCCXInteractionProperty()
    {
        if (!_writer || !_caseData)return false;

        // 获取相互作用属性管理器
        auto interactionPropertyManager = _caseData->getInteractionPropertyManager();
        int count = interactionPropertyManager->getDataCount();
        QTextStream* stream = _writer->getStream();

        // 写出相互作用属性
        bool okTitle = false;
        for (int i = 0; i < count; ++i)
        {
            // 动态转换为FITKAbaAbstractInteractionProperty类型
            auto interactionProp = dynamic_cast<Interface::FITKAbaAbstractInteractionProperty*>(interactionPropertyManager->getDataByIndex(i));

            // 如果转换失败，继续处理下一个
            if (!interactionProp)continue;
            if (!okTitle)
            {
                okTitle = true;
                *stream << "**" << endl;
                *stream << "** INTERACTION PROPERTIES" << endl;
                *stream << "**" << endl;
            }

            // 通过工厂创建
            auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorInteractionProperty>("CCXINP", interactionProp);
            if (adaptor == nullptr) return false;
            adaptor->setFileWriter(_writer);
            adaptor->setCaseData(_caseData);
            adaptor->setDataObject(interactionProp);
            bool ok = adaptor->adaptW();
            delete adaptor;
            if (!ok)
            {
                _writer->consoleMessage(3, QString("Write Interaction Property Error,File:%1 Line:%2").arg(__FILE__).arg(__LINE__));
                return false;
            }
        }
        return true;
    }

    bool FITKCCXAdaptorCase::writeCCXInitialBoundary()
    {
        if (!_writer || !_caseData)return false;
        auto boundaryManager = _caseData->getBCManager();
        int count = boundaryManager->getDataCount();
        QTextStream* stream = _writer->getStream();

        //获取initStepId
        auto stepManager = _caseData->getStepManager();
        if (!stepManager)return false;
        if (stepManager->getDataCount() < 1)return false;
        int initStepId = stepManager->getDataByIndex(0)->getDataObjectID();
        bool okTitle = false;
        for (int i = 0; i < count; ++i)
        {
            auto boundary = dynamic_cast<Interface::FITKAbaAbstractBoundaryCondition*>(boundaryManager->getDataByIndex(i));
            if (!boundary)continue;
            if (boundary->getCreatedStep() != initStepId)continue;
            if (!okTitle)
            {
                okTitle = true;
                *stream << "**" << endl;
                *stream << "** BOUNDARY CONDITIONS" << endl;
                *stream << "**" << endl;
            }

            //通过工厂创建
            auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorBoundary>("CCXINP", boundary);
            if (adaptor == nullptr) return false;
            adaptor->setFileWriter(_writer);
            adaptor->setCaseData(_caseData);
            adaptor->setDataObject(boundary);
            adaptor->setModelInfoManager(_modelInfoManager);
            bool ok = adaptor->adaptW();
            delete adaptor;
            if (!ok)
            {
                _writer->consoleMessage(3, QString("Write Initial Boundary Error,File:%1 Line:%2").arg(__FILE__).arg(__LINE__));
                return false;
            }
        }
        return true;
    }

    bool FITKCCXAdaptorCase::writeCCXInteraction()
    {
        if (!_writer || !_caseData)return false;

        QTextStream* stream = _writer->getStream();

        // 写出(Interaction)相互作用
        Interface::FITKAbaInteractionManager* _interactionManager = _caseData->getInteractionManager();
        if (_interactionManager == nullptr) return false;
        Interface::FITKAbaAbstractInteraction* initInteraction{};
        for (int i = 0; i < _interactionManager->getDataCount(); ++i)
        {
            auto interction = _interactionManager->getDataByIndex(i);
            if (interction == nullptr) continue;

            if (interction->getCreatedStep() == -1)
            {
                initInteraction = interction;
                break;
            }
        }
        if (initInteraction == nullptr) return true;

        *stream << "**" << endl;
        *stream << "** INTERACTIONS" << endl;
        *stream << "**" << endl;

        // 用于判断边界是否激活
        if (!initInteraction->getActiveState()) return true;
        //QString op;
        //int stepId = this->writeBoundaryDataType(interaction, op);
        //if (stepId == 0)continue;

        *stream << QString("** Interaction: general_contact") << endl;
        
        // 通过工厂创建
        auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorInteraction>("CCXINP", initInteraction);
        if (adaptor == nullptr) return false;
        adaptor->setFileWriter(_writer);
        adaptor->setCaseData(_caseData);
        auto initStepData = _caseData->getStepManager()->getDataByName("Initial");
        adaptor->setStepData(initStepData);
        adaptor->setDataObject(initInteraction);
        adaptor->setModelInfoManager(_modelInfoManager);
        bool ok = adaptor->adaptW();
        delete adaptor;
        if (!ok) _writer->consoleMessage(3, QString("Write Interaction Error,File:%1 Line:%2").arg(__FILE__).arg(__LINE__));
        return ok;
    }

    bool FITKCCXAdaptorCase::writeCCXStep(Interface::FITKAbaAbstractStep* step)
    {
        // 通过工厂创建
        auto adaptor = FITKIOADAPTORFACTORY->createT<FITKCCXAdaptorStep>("CCXINP", "Interface::FITKAbaAbstractStep");
        if (adaptor == nullptr)
            return false;

        //设置读取器
        adaptor->setFileWriter(_writer);
        adaptor->setDataObject(step);
        adaptor->setCaseData(_caseData);
        adaptor->setModelInfoManager(_modelInfoManager);
        bool ok = adaptor->adaptW();
        delete adaptor;
        if (!ok) 
           _writer->consoleMessage(3, QString("Write Step Error,File:%1 Line:%2").arg(__FILE__).arg(__LINE__));
        return ok;
    }

    bool  FITKCCXAdaptorCase::isBothCouplingDynamic()
    {
        // 是否存在coupling（耦合）
        bool existCoupling = false;

        // 查找约束类型中是否包含coupling
        auto constraintManager = _caseData->getConstraintManager();
        if (!constraintManager)return false;
        int count = constraintManager->getDataCount();
        for (int i = 0; i < count; ++i)
        {
            auto data = constraintManager->getDataByIndex(i);
            Interface::FITKAbaAbstractConstraint* constraint = dynamic_cast<Interface::FITKAbaAbstractConstraint*>(data);
            if (!constraint)continue;

            // 获取类型
            Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType type = constraint->getConstraintType();

            // 根据约束类型调用相应的写入函数
            if (type == Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType::Coupling)
            {
                existCoupling = true;
                break;
            }
        }

        // 是否存在Dynamic
        bool exitDynamic = false;

        // 查找分析步类型中是否包含Dynamic
        int stepNum = _caseData->getStepManager()->getDataCount();
        if (stepNum > 1)
        {
            for (int i = 1; i < stepNum; ++i)
            {
                auto absStep = _caseData->getStepManager()->getDataByIndex(i);
                if (!absStep) continue;

                auto stepType = absStep->getStepType();

                if (stepType == Interface::FITKAbaAbstractStep::FITKAbaStepType::DynamicExplicit)
                {
                    exitDynamic = true;
                    break;
                }
            }
        }

        //if (exitDynamic && existCoupling)
        //{
            // 写出不支持动态分析步中包含coupling约束类型
            //_writer->consoleMessage(2, "Calculix does not support coupling is included in the dynamic analysis step");
        //}

        // 动态分析步中是否包含coupling约束类型
        return exitDynamic && existCoupling;
    }
}


